home *** CD-ROM | disk | FTP | other *** search
- /*
- * C compiler
- * ==========
- *
- * Copyright 1989, 1990, 1991 Christoph van Wuellen.
- * Credits to Matthew Brandt.
- * All commercial rights reserved.
- *
- * This compiler may be redistributed as long there is no
- * commercial interest. The compiler must not be redistributed
- * without its full sources. This notice must stay intact.
- *
- * History:
- *
- * 1989 starting an 68000 C compiler, starting with material
- * originally by M. Brandt
- * 1990 68000 C compiler further bug fixes
- * started i386 port (December)
- * 1991 i386 port finished (January)
- * further corrections in the front end and in the 68000
- * code generator.
- * The next port will be a SPARC port
- */
-
- #include "config.h"
-
- #define MAX_WIDTH 60
-
- #ifdef MC680X0
- #ifdef TARGET_JAS
-
- #include "chdr.h"
- #include "expr.h"
- #include "gen.h"
- #include "cglbdec.h"
-
- #ifdef MULTIPLE_ASSEMBLERS
- #define PRIVATE static
- #undef put_code
- #undef put_string
- #undef put_label
- #undef put_byte
- #undef put_char
- #undef put_word
- #undef put_long
- #undef put_pointer
- #undef put_short
- #undef put_storage
- #undef dumplits
- #undef put_external
- #undef put_global
- #undef put_align
- #undef nl
- #undef cseg
- #undef dseg
- #undef put_float
- #undef put_double
- #undef put_longdouble
- #else
- #define PRIVATE
- #endif /* MULTIPLE_ASSEMBLERS */
-
- enum e_gt {
- bytegen, wordgen, longgen, floatgen, nogen
- };
- enum e_sg {
- noseg, codeseg, dataseg, bssseg
- };
-
- #if defined(__STDC__) || defined(__cplusplus)
- #define P_(s) s
- #else
- #define P_(s) ()
- #endif
-
- /* out68k_jas.c */
- static void putop P_((OPCODE));
- static void putconst P_((EXPR *));
- static void putlen P_((int));
- static void putamode P_((ADDRESS *));
- static void put_mask P_((REGMASK));
- static void put_rmask P_((REGMASK));
- static void put_smask P_((REGMASK));
- static void putreg P_((int));
- static void put_header P_((enum e_gt, SIZE));
- static void seg P_((enum e_sg, char *));
- static void bseg P_((void));
- PRIVATE void put_string P_((char *));
- PRIVATE void put_align P_((SIZE));
- PRIVATE void put_long P_((long));
- PRIVATE void nl P_((void));
- PRIVATE void cseg P_((void));
- PRIVATE void dseg P_((void));
- PRIVATE void put_label P_((LABEL));
- PRIVATE void put_external P_((char *));
- PRIVATE void put_byte P_((int));
- PRIVATE void put_char P_((int));
-
- #undef P_
-
- /* variable initialization */
-
- static enum e_gt gentype = nogen;
- static enum e_sg curseg = noseg;
- static int outcol = 0;
- static SIZE align_type;
-
- #define prefix "L"
- #define comment ";"
-
- static char *opl[] = {
- "move", /* op_move */
- "moveq", /* op_moveq */
- "add", /* op_add */
- "add", /* op_addi */
- "addq", /* op_addq */
- "sub", /* op_sub */
- "sub", /* op_subi */
- "subq", /* op_subq */
- "muls", /* op_muls */
- "mulu", /* op_mulu */
- "divs", /* op_divs */
- "divu", /* op_divu */
- "and", /* op_and */
- "and", /* op_andi */
- "or", /* op_or */
- "or", /* op_ori */
- "eor", /* op_eor */
- "asl", /* op_asl */
- "lsr", /* op_lsr */
- "jmp", /* op_jmp */
- "jsr", /* op_jsr */
- "movem", /* op_movem */
- "rts", /* op_rts */
- "bra", /* op_bra */
- "beq", /* op_beq */
- "bne", /* op_bne */
- "blt", /* op_blt */
- "ble", /* op_ble */
- "bgt", /* op_bgt */
- "bge", /* op_bge */
- "bhi", /* op_bhi */
- "bcc", /* op_bhs */
- "bcs", /* op_blo */
- "bls", /* op_bls */
- "btst", /* op_btst */
- "tst", /* op_tst */
- "ext", /* op_ext */
- "lea", /* op_lea */
- "swap", /* op_swap */
- "neg", /* op_neg */
- "not", /* op_not */
- "cmp", /* op_cmp */
- "clr", /* op_clr */
- "link", /* op_link */
- "unlk", /* op_unlk */
- "pea", /* op_pea */
- "cmp", /* op_cmpi */
- "dbra", /* op_dbra */
- "asr", /* op_asr */
- "rol", /* op_rol */
- "ror", /* op_ror */
- "seq", /* op_seq */
- "sne", /* op_sne */
- "slt", /* op_slt */
- "sle", /* op_sle */
- "sgt", /* op_sgt */
- "sge", /* op_sge */
- "shi", /* op_shi */
- "scc", /* op_shs */
- "scs", /* op_slo */
- "sls", /* op_sls */
- "st", /* op_st */
- #ifdef TRAP_GEN
- "trap", /* op_trap */
- #endif /* TRAP_GEN */
- comment"line", /* op_line */
- 0, /* op_label */
- };
-
- static void
- putop(op)
- OPCODE op;
- {
- if (op >= OP_MIN && op <= OP_MAX && opl[op] != (char *)0)
- oprintf ("\t%s",opl[op]);
- else
- fatal(__FILE__,"putop","illegal opcode %d",op);
- }
-
- static void
- putconst(offset)
- /*
- * put a constant to the output file.
- */
- EXPR *offset;
- {
-
- switch (offset->nodetype) {
- case en_autocon:
- case en_icon:
- oprintf("%ld", offset->v.i);
- break;
- #ifndef FLOAT_BOOTSTRAP
- #ifdef FLOAT_MFFP
- case en_fcon:
- oprintf("$%lx", genffp(offset->v.f));
- break;
- #endif /* FLOAT_MFFP */
- #endif /* FLOAT_BOOTSTRAP */
- case en_labcon:
- oprintf(prefix"%u", (unsigned)offset->v.l);
- break;
- case en_nacon:
- oprintf("%s",outlate(offset->v.sp));
- break;
- case en_add:
- putconst(offset->v.p[0]);
- oprintf("+");
- putconst(offset->v.p[1]);
- break;
- case en_sub:
- putconst(offset->v.p[0]);
- oprintf("-");
- putconst(offset->v.p[1]);
- break;
- case en_uminus:
- oprintf("-");
- putconst(offset->v.p[0]);
- break;
- default:
- fatal(__FILE__,"putconst","illegal constant node %d",offset->nodetype);
- break;
- }
- }
-
- static void
- putlen(l)
- /*
- * append the length field to an instruction.
- */
- int l;
- {
- if (l == 0)
- return;
- oprintf(".");
- switch (l) {
- case 1:
- oprintf("b");
- break;
- case 2:
- oprintf("w");
- break;
- case 4:
- oprintf("l");
- break;
- default:
- fatal(__FILE__,"putlen","illegal length field %d",l);
- break;
- }
- }
-
- static void
- putamode(ap)
- /*
- * output a general addressing mode.
- */
- ADDRESS *ap;
- {
- switch (ap->mode) {
- case am_immed:
- oprintf("#");
- /*FALLTHRU*/
- case am_direct:
- putconst(ap->offset);
- break;
- case am_areg:
- oprintf("a%d", ap->preg);
- break;
- case am_dreg:
- oprintf("d%d", ap->preg);
- break;
- case am_ind:
- oprintf("(a%d)", ap->preg);
- break;
- case am_ainc:
- oprintf("(a%d)+", ap->preg);
- break;
- case am_adec:
- oprintf("-(a%d)", ap->preg);
- break;
- case am_indx:
- putconst(ap->offset);
- oprintf("(a%d)", ap->preg);
- break;
- case am_indx2:
- putconst(ap->offset);
- oprintf("(a%d,d%d.l)", ap->preg, ap->sreg);
- break;
- case am_indx3:
- putconst(ap->offset);
- oprintf("(a%d,a%d.l)", ap->preg, ap->sreg);
- break;
- #ifdef JAS_PATCH
- case am_indx4:
- putconst(ap->offset);
- oprintf("(a%d,d%d.w)", ap->preg, ap->sreg);
- break;
- #endif /* JAS_PATCH */
- case am_rmask:
- put_rmask((REGMASK) ap->offset->v.i);
- break;
- case am_smask:
- put_smask((REGMASK) ap->offset->v.i);
- break;
- case am_line:
- putconst(ap->offset);
- break;
- default:
- fatal(__FILE__,"putamode","illegal address mode %d",ap->mode);
- break;
- }
- }
-
- PRIVATE void
- put_code(op, len, aps, apd)
- /*
- * output a generic instruction.
- */
- ADDRESS *aps, *apd;
- int len;
- OPCODE op;
- {
- putop(op);
- putlen(len);
- if (aps != 0) {
- oprintf("\t");
- putamode(aps);
- if (apd != 0) {
- oprintf(",");
- putamode(apd);
- }
- }
- oprintf("\n");
- }
-
- static void
- put_mask(mask)
- /*
- * generate a register mask.
- */
- REGMASK mask;
- {
- int i;
- BOOL pending = 0;
- if (mask & 1) {
- putreg(0);
- pending = 1;
- }
- for (i = 1; i <= 15; i++)
- if ((mask = mask >> 1) & 1) {
- if (pending)
- oprintf("/");
- putreg(i);
- pending = 1;
- }
- }
-
- static void
- put_smask(mask)
- /*
- * generate a register mask for save.
- */
- REGMASK mask;
- {
- put_mask(mask);
- }
-
- static void
- put_rmask(mask)
- /*
- * generate a register mask for restore.
- */
- REGMASK mask;
- {
- put_mask(mask);
- }
-
- static void
- putreg(r)
- /*
- * generate a register name from a tempref number.
- */
- int r;
- {
- if (r < 8)
- oprintf("d%d", r);
- else
- oprintf("a%d", r - 8);
- }
-
- PRIVATE void
- put_string(s)
- /*
- * generate a named label.
- */
- char *s;
- {
- oprintf("%s:\n",outlate(s));
- }
-
- PRIVATE void
- put_label(lab)
- /*
- * output a compiler generated label.
- */
- LABEL lab;
- {
- oprintf(prefix"%u:\n", (unsigned int)lab);
- }
-
-
- static void
- put_header (gtype, al)
- enum e_gt gtype;
- SIZE al;
- {
- static char *directive[] = {
- "dc.b\t", /* bytegen */
- "dc.w\t", /* wordgen */
- "dc.l\t", /* longgen */
- };
-
- if (gentype != gtype || outcol >= MAX_WIDTH) {
- put_align(al);
- gentype = gtype;
- outcol = 15;
- oprintf("\t%s", directive[gtype]);
- } else
- oprintf(",");
- }
-
- PRIVATE void
- put_byte(val)
- int val;
- {
- put_header(bytegen, (SIZE)AL_CHAR);
- oprintf("%d", val & 0x00ff);
- outcol += 4;
- }
-
- PRIVATE void
- put_char(val)
- int val;
- {
- put_byte(val);
- }
-
- PRIVATE void
- put_word(val)
- int val;
- {
- put_header(wordgen, (SIZE)AL_SHORT);
- oprintf("%d", val & 0xffff);
- outcol += 6;
- }
-
- #ifndef FLOAT_BOOTSTRAP
- #ifdef FLOAT_IEEE
- PRIVATE void
- put_float(val)
- double val;
- {
- unsigned long ul;
- ieee_single(val, &ul);
- put_long((long) ul);
- }
-
- PRIVATE void
- put_double(val)
- double val;
- {
- unsigned long ul[2];
- ieee_double(val, ul);
- put_long ((long) ul[0]);
- put_long ((long) ul[1]);
- }
- PRIVATE void
- put_longdouble(val)
- double val;
- {
- unsigned long ul[2];
- ieee_double(val, ul);
- put_long ((long) ul[0]);
- put_long ((long) ul[1]);
- }
- #endif /* FLOAT_IEEE */
- #ifdef FLOAT_MFFP
- PRIVATE void
- put_float(val)
- double val;
- {
- put_long((long) genffp(val));
- }
-
- PRIVATE void
- put_double(val)
- double val;
- {
- put_long((long) genffp(val));
- }
-
- PRIVATE void
- put_longdouble(val)
- double val;
- {
- put_long((long) genffp(val));
- }
- #endif /* FLOAT_MFFP */
- #endif /* FLOAT_BOOTSTRAP */
-
- PRIVATE void
- put_long(val)
- long val;
- {
- put_header (longgen, (SIZE)AL_LONG);
- oprintf("$%lx", val);
- outcol += 10;
- }
-
- #ifndef RELOC_BUG
- PRIVATE void
- put_short(node)
- EXPR *node;
- {
- put_header (wordgen, (SIZE)AL_SHORT);
- putconst(node);
- outcol += 10;
- }
- #endif /* RELOC_BUG */
-
- PRIVATE void
- put_pointer(node)
- EXPR *node;
- {
- put_header (longgen, (SIZE)AL_POINTER);
- putconst(node);
- outcol += 10;
- }
-
- PRIVATE void
- put_storage(sp, al)
- SYM *sp;
- SIZE al;
- {
- bseg();
- put_align(al);
- #if 0
- if (sp->storage_class == sc_static) {
- put_label (sp->value.l);
- oprintf("\tds.b\t");
- } else
- oprintf("\tcomm\t%s,", outlate(sp->name));
- oprintf("%ld\n", sp->tp->size);
- #else
- if (sp->storage_class == sc_static) {
- put_label (sp->value.l);
- } else
- put_string (sp->name);
- oprintf("\tds.b\t%ld\n", sp->tp->size);
- #endif
- }
-
-
- PRIVATE void
- dumplits()
- /*
- * dump the string literal pool.
- * if we are producing single copies of strings (which should therefore
- * be read only we put them in the text segement - else in the data segment.
- */
- {
- char *cp;
- int len;
- if (trad_option || IandD_option)
- dseg();
- else
- cseg();
- for ( ; strtab != 0; strtab = strtab->next) {
- nl();
- put_label(strtab->label);
- cp = strtab->str;
- for (len = strtab->len; len--; )
- put_char(*cp++);
- put_byte(0);
- }
- nl();
- }
-
- /*ARGSUSED*/
- PRIVATE void
- put_external(s)
- char *s;
- /* put the definition of an external name in the ouput file */
- {
- s = s; /* keep the compiler happy */
- }
-
- PRIVATE void
- put_global(s)
- char *s;
- /* put the definition of a global name in the output file */
- {
- nl();
- oprintf("\tglobl\t%s\n", outlate(s));
- }
-
- PRIVATE void
- put_align(al)
- SIZE al;
- /* align the following data */
- {
- nl();
- if (al > align_type) {
- switch (al) {
- case 2:
- case 4:
- oprintf("\teven\n");
- break;
- }
- }
- align_type = al;
- }
-
- PRIVATE void
- nl()
- {
- static BOOL init_done = 0;
- if (init_done == 0) {
- #ifdef VERBOSE
- time_t time_of_day;
- VOIDCAST time (&time_of_day);
- #endif /* VERBOSE */
- init_done++;
- oprintf(comment" Generated by %s v%s, %s (%s) from \"%s\"\n",
- PROGNAME, VERSION, LAST_CHANGE_DATE, __DATE__, act_file);
- #ifdef VERBOSE
- oprintf(comment" Compilation date/time: %s\n", ctime(&time_of_day));
- #endif /* VERBOSE */
- } else if (outcol > 0) {
- oprintf("\n");
- gentype = nogen;
- outcol = 0;
- }
- }
-
- static void
- seg(segtype, segname)
- enum e_sg segtype;
- char *segname;
- {
- nl();
- if (curseg != segtype) {
- oprintf("\t%s\n", segname);
- curseg = segtype;
- align_type = 0;
- }
- }
-
- PRIVATE void
- cseg()
- {
- seg(codeseg,"text");
- }
-
- PRIVATE void
- dseg()
- {
- seg(dataseg,"data");
- }
-
- static void
- bseg()
- {
- seg(bssseg,"bss");
- }
-
- #ifdef MULTIPLE_ASSEMBLERS
- struct funcs jas68k_funcs = {
- put_code,
- put_string,
- put_label,
- put_byte,
- put_char,
- put_word,
- put_long,
- put_pointer,
- #ifndef RELOC_BUG
- put_short,
- #endif /* RELOC_BUG */
- put_storage,
- dumplits,
- put_external,
- put_global,
- put_align,
- nl,
- cseg,
- dseg,
- #ifdef FLOAT_SUPPORT
- put_float,
- put_double,
- put_longdouble
- #endif /* FLOAT_SUPPORT */
- };
- #endif /* MULTIPLE_ASSEMBLERS */
- #endif /* TARGET_JAS */
- #endif /* MC680X0 */
-